fix(gateway): 修复 WebSocket 大图像首帧失败与账号重复恢复 - #446
Merged
qxcnm merged 4 commits intoAug 22, 2026
Conversation
Owner
|
审查结论:暂不合并,先保持 Draft。 这次改动的方向有价值:在 #442 的 Responses WebSocket 恢复基础上补了首帧失败后的账号排除,并增加了 permessage-deflate 与约 34 MiB 图像上下文的回归覆盖。当前我在隔离 worktree 做到:
但目前还不具备可合并条件:
请先转为 Ready for review,补齐 CI(至少 service workspace、web/desktop build、Tauri 目标),并确认压缩协商被上游拒绝时的未压缩兼容路径和 pinned fork 的长期维护方式;验证稳定后我再复核合并。 |
MDX-Tom
marked this pull request as ready for review
August 22, 2026 09:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(gateway): 对齐 Responses WebSocket 压缩协商与首帧恢复
摘要
本 PR 在 PR #430 的心跳、连接上限、大图像帧和有界恢复基础上,继续修复 Responses WebSocket 在大上下文首帧阶段断开、失败账号重复恢复,以及部分上游拒绝压缩协商的问题。
本次改动覆盖:
tokio-tungstenite/tungstenitefork revision;permessage-deflate,并保留 256 MiB message/frame 上限;400/426或扩展拒绝信息拒绝压缩时,只重新建立一次不带压缩扩展的连接;response.completed才确认 WebSocket 成功,恢复预算耗尽后继续由客户端进入 HTTP fallback;官方行为基线
实现以官方 Responses WebSocket Mode 和官方 Codex Responses WebSocket 客户端 为基准:
response.create消息开始;response.completed才确认该轮完成;问题与根因
1. 大图像上下文首帧发送阶段的兼容性不足
包含多张内联图像时,完整
response.create文本帧可能达到数十 MiB。此前传输层没有完整对齐官方 fork 和扩展协商配置,首帧发送阶段更容易出现:此前的账号恢复逻辑已经处理了大帧发送失败,但如果上游连接策略本身拒绝
permessage-deflate,仍会在连接阶段失败。2. 首帧失败后的恢复可能重复选择原账号
首帧发送失败后,conversation-bound 候选列表可能再次把原账号放在头部,导致同一失败 socket 被重复使用,其他可选账号无法接收首帧。
3. 依赖与独立 Tauri workspace 容易漂移
根 workspace 与
apps/src-tauri是两个 Cargo workspace。只在其中一个 workspace 固定 fork,或只生成其中一个 lockfile,会使桌面构建和服务构建采用不同的 WebSocket 行为。修改内容
官方 WebSocket 传输对齐
apps/src-tauri同步固定:tokio-tungstenitefork revision0e5b2d73aa18dd9f0a50ee9ff199d5aef7594186;tungstenitefork revision4fffad30fe373adbdcffab9545e9e9bf4f2fc19f。deflate/proxyfeature,并保持官方压缩配置;400/426或明确的permessage-deflate/ WebSocket 扩展拒绝信息拒绝压缩,只重新握手一次且不发送扩展;有界首帧恢复与账号轮换
CI 与依赖维护
scripts/ci/check-websocket-pins.sh,校验两个 workspace 的 manifest、lockfile 和 fork revision 同步;docs/zh-CN/WEBSOCKET_DEPENDENCY_MAINTENANCE.md,记录 fork 的来源、升级步骤、压缩回退条件和验证要求;.github/workflows/ci.yml:cargo check --workspace --all-targets;codex_skills测试失败阻塞本 PR 的传输验证;apps/out,再运行codexmanager-web测试;回归覆盖
新增
official_responses_websocket_retries_without_compression_after_upstream_rejection:permessage-deflate;400 unsupported extension: permessage-deflate;Sec-WebSocket-Extensions;response.create完整转发;response.completed。同时保留并继续验证:
验证结果
已通过:
bash scripts/ci/check-websocket-pins.sh;cargo fmt --all -- --check;git diff --check;cargo test -p codexmanager-service --lib official_responses_websocket_ --no-fail-fast— 17 passed;cargo test -p codexmanager-service --lib send_websocket_upstream_request_ --no-fail-fast— 5 passed;pnpm -C apps run build:desktop;cargo test -p codexmanager-web --no-fail-fast— 26 passed;cargo tauri build --bundles app;完整 service lib 串行验证结果为
1421 passed / 1 failed / 3 ignored。唯一失败是现有codex_skills::tests::directory_import_detects_same_size_file_replacement_and_fifo_entries的跨平台文件替换断言(Linux CI 中表现为返回了仍可读的文件句柄),单独运行也可复现,与本 PR 修改文件无关;因此 CI 保留 workspace target 编译检查,并将服务测试聚焦于本 PR 的 WebSocket 回归集合。兼容性与边界
/v1/responsesendpoint 形状;